﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Web.Optimization;
using MvcExtensions.Extensions;
using Newtonsoft.Json;

namespace MvcExtensions.Core
{
    //http://stackoverflow.com/questions/18577061/asp-net-mvc-web-api-custom-dynamic-bundle-working-in-production-but-not-dev
    public class CustomBundle : Bundle
    {
        private readonly List<Type> _registerdTypes = new List<Type>();

        public CustomBundle(string virtualPath)
            : base(virtualPath, new CustomBundleTransform())
        {
        }

        public IEnumerable<Type> RegisterdTypes
        {
            get { return _registerdTypes; }
        }

        public virtual CustomBundle Include(Type type)
        {
            _registerdTypes.Add(type);
            return this;
            //return Include(string.Format("~/{0}", type.Name)) as CustomBundle;
        }
        public override BundleResponse GenerateBundleResponse(BundleContext context)
        {
            return base.GenerateBundleResponse(context);
        }

        public override BundleResponse ApplyTransforms(BundleContext context, string bundleContent, IEnumerable<BundleFile> bundleFiles)
        {
            return base.ApplyTransforms(context, bundleContent, bundleFiles);
        }
    }

    public class CustomBundleTransform : IBundleTransform
    {
        public void Process(BundleContext context, BundleResponse response)
        {
            var bundle = context.BundleCollection.FirstOrDefault(b => b.Path == context.BundleVirtualPath) as CustomBundle;

            if (bundle == null)
                return;

            foreach (var registerdType in bundle.RegisterdTypes)
            {
                KOViewModelBuilder.BuildViewModel(registerdType);
            }

            if (context.EnableOptimizations)
            {
                var script = new StringBuilder(2048);
                foreach (var builder in KOViewModelBuilder.KnockoutViewModelDictionary)
                {
                    script.Append("\n");
                    script.Append(builder.Value);
                }

                response.Content = script.ToString(); //string.Format(";var obj = {0};", JsonConvert.SerializeObject(bundle.KeyValues));
                response.ContentType = "application/javascript";
            }
            else
            {
                var customePath = string.Format("{0}.debug", bundle.Path);

                var directoryPath = HttpContext.Current.Server.MapPath(customePath);

                if (!Directory.Exists(directoryPath))
                {
                    Directory.CreateDirectory(directoryPath);
                }

                var files = new List<BundleFile>();

                response.Files = files;
                foreach (var builder in KOViewModelBuilder.KnockoutViewModelDictionary)
                {
                    var virtualFileName = string.Format("{0}/{1}.js", customePath, builder.Key);
                    files.Add(new CustomBundleFile(customePath, new CustomVirtualFile(virtualFileName)));

                    var fileName = string.Format("{0}/{1}.js", directoryPath, builder.Key);

                    File.WriteAllText(fileName, builder.Value.ToString());
                }
            }
            response.Cacheability = HttpCacheability.Server;
            context.UseServerCache = false;

        }
    }

    public class CustomVirtualFile : VirtualFile
    {
        public CustomVirtualFile(string virtualPath)
            : base(virtualPath)
        {
        }

        public override bool IsDirectory
        {
            get { return false; }
        }

        public override Stream Open()
        {
            throw new NotImplementedException();
        }
    }

    public class CustomBundleFile : BundleFile
    {
        public CustomBundleFile(string includedVirtualPath, VirtualFile file)
            : base(includedVirtualPath, file, new List<IItemTransform> { new CustomItemTransform() })
        {
            
        }
    }


    public class CustomItemTransform : IItemTransform
    {

        public string Process(string includedVirtualPath, string input)
        {
            throw new NotImplementedException();
        }
    }
}
